package com.ar4j.handler;

import java.lang.reflect.Method;

import net.sf.cglib.proxy.MethodProxy;

import com.ar4j.ActiveRecord;
import com.ar4j.ActiveRecordContext;
import com.ar4j.ActiveRecordMetadata;
import com.ar4j.ActiveRecordReadOnlyException;

/**
 * A method handler that delegates its invocation to another handler when an active record's
 * read only flag is set to false, and throws an exception when read only is set to true.
 */
public class ReadOnlyAwareDelegatingMethodHandler implements IMethodHandler {
  private IMethodHandler delegate;
  
  public ReadOnlyAwareDelegatingMethodHandler(IMethodHandler delegate) {
    this.delegate = delegate;
  }
  
  @Override
  public void init(ActiveRecordMetadata metadata, Method method) {
    delegate.init(metadata, method);
  }

  @Override
  public Object intercept(ActiveRecordMetadata metadata, ActiveRecordContext context, Object target, Method method, Object[] args, MethodProxy proxy) 
    throws Throwable {
    
    ActiveRecord<?> record = (ActiveRecord<?>) target;
    if(record.getContext().isReadOnly()) {
      throw new ActiveRecordReadOnlyException("Cannot execute " + method.getName() + " on a read only record of type: " + record.getBaseClass().getName());
    }
    
    return delegate.intercept(metadata, context, target, method, args, proxy);
  }
    
}
